Kurt Hsu's blog

The Rails developer in taiwan.


  • 首頁

  • 標籤

  • 分類

  • 歸檔

[Angular-1]controller的父子關係變數溝通(通訊)測試

發表於 2017-05-11 更新於 2019-08-20 分類於 Angular , Angular1

最近在重整公司專案一個controller一個頁面吃到完的hard code,網路上找了許多規範,大家都很推johnpapa的angular規範,但在父子關係的controller之間的通訊是如何呢?

在這邊紀錄一下我直接用實測的方式做出來,還不是很清楚底層發生了什麼事情。

父子都注入$scope的話

在這邊我就不多贅述創造module的部分,只針對controller寫範例:

1
2
3
4
5
6
<div ng-controller="parentCtrl">
{{ father }}
<div ng-controller="childCtrl">
{{ son }}
</div>
</div>

這是我公司最一開始html的寫法,我想也是大家剛接觸angular的寫法,我來看看JS的部分(參照johnpapa的規範寫兩個JS檔案):

parentCtrl.js
1
2
3
4
5
6
7
8
9
10
angular
.module('app')
.controller('parentCtrl', parentCtrl)

parentCtrl.$inject = ['$scope'];

function parentCtrl ($scope) {
$scope.father = "hasFather";
$scope.son = "hasSon";
}

接下來創造childCtrl,裡面沒有任何的程式碼,純粹console.log變數出來看:

childCtrl.js
1
2
3
4
5
6
7
8
9
10
angular
.module('app')
.controller('childCtrl', childCtrl)

childCtrl.$inject = ['$scope'];

function childCtrl ($scope) {
console.log($scope.father);//hasFather
console.log($scope.son);//hasSon
}

發現在childCtrl其實就跟parentCtrl共用$scope了!
更明顯的是可以直接在html裡面看到結果,這讓我迷思的一點是大家都說每一個controller都有屬於自己的$scope,但在父子關係的controller似乎不是這樣子。

##父子使用this去注入$scope的話
在剛剛的例子之後,接下來我們親愛的johnpapa說不要這樣寫,因為html和變數一多會很難以維護,意思就是不要一直用$scope宣告變數,那該怎麼讓變數跟自己的controller綁定?

有一版的angular新增了controller as ctrl的這個功能,現在我們可以很直覺的直接在html裡面看得出這個變數是屬於哪個controller的。

來看看html做了哪些更新:

1
2
3
4
5
6
<div ng-controller="parentCtrl as parent">
{{ parent.father }}
<div ng-controller="childCtrl as child">
{{ child.son }}
</div>
</div>

使用controller as之後表達式一定要這樣寫才行喔!!
這樣就很清楚知道這個表達式的變數是哪個controller裡面的。

那麼controller怎麼使用johnpapa所說的this呢?

parentCtrl.js
1
2
3
4
5
6
7
8
9
10
angular
.module('app')
.controller('parentCtrl', parentCtrl)

parentCtrl.$inject = ['$scope'];

function parentCtrl ($scope) {
var self = this;
this.father = "hasFather";
}

childCtrl也要有自己的變數囉!但是我們依然可以測試一下childCtrl到底吃不吃得到parentCtrl的變數,我們用console.log來查查:

childCtrl.js
1
2
3
4
5
6
7
8
9
10
11
angular
.module('app')
.controller('childCtrl', childCtrl)

childCtrl.$inject = ['$scope'];

function childCtrl ($scope) {
var self = this;
this.son = "hasSon";
console.log(self.father);//undefiend
}

此時html都可以正常顯示的,因為parent.father有正確的在parentCtrl裡宣告,而child.son有正確的在childCtrl裡宣告,但是在childCtrl裡已經找不到self.father的變數囉!

這邊還蠻直覺的,因為畢竟在兩個controller裡面都宣告自己的this,我們也可以在兩個環境都下console.log(this);就會看出他們確實指向不同的物件(有不同的變數環境)。

接下來最有趣的東西來了

如果我們在childCtrl把var self = this;拿走呢?猜猜看會發生什麼事?

childCtrl.js
1
2
3
4
5
6
7
8
9
10
angular
.module('app')
.controller('childCtrl', childCtrl)

childCtrl.$inject = ['$scope'];

function childCtrl ($scope) {
this.son = "hasSon";
console.log(self);//會發生什麼事情!?
}

我在下console.log(self);以前會認為因為在childCtrl找不到self所以向外看到了parentCtrl有self,所以應該會指向他,但是…..BAAAANG!!!

如果沒有宣告self的話他竟然指向了window!!!
WTF??
self不是被我宣告是指向parentCtrl這個物件裡嗎XD?

總之測試告一段落,因為我本來一直苦惱著要怎麼讓兩個controller溝通,網路上查就有三大種方法,第一個自己創service,第二個是使用$broadcast的事件,再來第三個是直接使用$rootScope,在這裡就不在贅述囉!

這是我自己測試出來的,如果大家有什麼好心得可以交流一下囉!

# Angular # controller
「直播」Nic拉你出坑,HTTP協定,CRUD與RESTful和MVC架構
[Angular-1]type file 使用原生 onchange 呼叫 angular function
  • 文章目錄
  • 本站概要

Kurt Hsu

Progress One Percent Every Day
171 文章
55 分類
163 標籤
RSS
  1. 1. 父子都注入$scope的話
    1. 1.1. 接下來最有趣的東西來了
© 2020 Kurt Hsu
由 Hexo 強力驅動 v3.8.0
|
主題 – NexT.Muse v7.3.0